package org.example.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.domain.dto.DTO;
import org.example.domain.dto.PageDTO;
import org.example.domain.po.ErpMenu;
import org.example.domain.po.ErpRole;
import org.example.domain.po.ErpRoleMenu;
import org.example.domain.po.ErpUser;
import org.example.domain.query.HomeQuery;
import org.example.domain.query.RoleQuery;
import org.example.domain.vo.ErpRoleVO;
import org.example.domain.vo.home.HomeDataVO;
import org.example.enums.RolePriceLimit;
import org.example.mapper.ErpMenuMapper;
import org.example.service.ErpRoleMenuService;
import org.example.service.ErpRoleService;
import org.example.mapper.ErpRoleMapper;
import org.example.utils.EnumUtil;
import org.example.utils.Result;
import org.example.utils.TreeUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author DELL
* @description 针对表【erp_role(角色表)】的数据库操作Service实现
* @createDate 2024-10-09 17:03:06
*/
@Service
@Transactional
public class ErpRoleServiceImpl extends ServiceImpl<ErpRoleMapper, ErpRole>
    implements ErpRoleService{
    
    @Resource
    private ErpRoleMapper erpRoleMapper;
    
    @Resource
    @Lazy
    private ErpRoleMenuService erpRoleMenuService;
    
    @Resource
    private ErpMenuMapper erpMenuMapper;
    
    @Override
    public boolean insertRole(ErpRole role) {
        return erpRoleMapper.insertRole(role) > 0;
    }
    
    /**
     * 根据租户id查询角色列表
     * @param tenantId 租户id
     */
    @Override
    public List<ErpRole> findRoleByTenantId(Long tenantId) {
//        LambdaQueryWrapper<ErpRoleVO> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(ErpRoleVO::getTenantId, tenantId).ne(ErpRoleVO::getName, "租户");
//        List<ErpRoleVO> list = baseMapper.findRoleByTenantId(tenantId);
        return lambdaQuery().eq(ErpRole::getTenantId, tenantId).ne(ErpRole::getName, "租户").list();
    }
    
    /**
     * 角色查询分页
     */
    @Override
    public PageDTO<ErpRoleVO> queryRolePage(RoleQuery query) {
        Long tenantId = query.getTenantId();
        String name = query.getName();
        String description = query.getDescription();
        // 1.构建分页条件
        Page<ErpRole> page = query.toMpPage();
        // 2. 分页查询
        Page<ErpRole> p = lambdaQuery()
                .eq(ErpRole::getTenantId, tenantId)
                .like(name != null, ErpRole::getName, name)
                .like(description != null, ErpRole::getDescription, description)
                .ne(ErpRole::getName, "租户")
                .orderByDesc(ErpRole::getId)
                .page(page);
        // 3.封装VO结果
        return PageDTO.of(p, erpRole ->{
            // 1.拷贝基础属性
            ErpRoleVO vo = BeanUtil.copyProperties(erpRole, ErpRoleVO.class);
            // 2.处理特殊逻辑
            vo.setPriceLimit(EnumUtil.getByValue(RolePriceLimit.class, vo.getPriceLimit()));
            return vo;
        });
    }
    
    /**
     * 授权菜单
     */
    @Override
    public boolean saveGrant(Map<String, Object> data) {
        Long roleId = Convert.convert(Long.class, data.get("roleId"));
        
        LambdaQueryWrapper<ErpRoleMenu> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ErpRoleMenu::getRoleId, roleId);
        erpRoleMenuService.remove(lambdaQueryWrapper);
        
        List<Integer> integerMenuIds = Convert.convert(List.class, data.get("menusId"));
        if (CollUtil.isEmpty(integerMenuIds)){
            return true;
        }
        List<Long> menuIds = integerMenuIds.stream().map(Integer::longValue).collect(Collectors.toList());
        menuIds = menuIds.stream().sorted().collect(Collectors.toList());
        
        // 平级菜单
        List<ErpMenu> menuList = new ArrayList<>();
        menuIds.forEach(id -> {
            // 查询出树形菜单
            if (id < 10) return;
            List<ErpMenu> menus = erpMenuMapper.findMenus(id);
            menus.forEach(item -> {
                TreeUtil.reversion(item, menuList);
            });
        });
        List<ErpRoleMenu> roleMenus = new ArrayList<>();
        List<ErpMenu> newMenuList = menuList.stream().distinct().collect(Collectors.toList());
        newMenuList.forEach(item -> roleMenus.add(new ErpRoleMenu(roleId, item.getId())));
        erpRoleMenuService.saveBatch(roleMenus);
        
        List<ErpRoleMenu> list = new ArrayList<>();
        menuIds.forEach(item -> list.add(new ErpRoleMenu(roleId, item)));
        return erpRoleMenuService.saveBatch(list);
    }
    
    @Override
    public boolean updateRole(ErpRole role) {
        return lambdaUpdate()
                .eq(ErpRole::getId, role.getId())
                .set(role.getName() != null, ErpRole::getName, role.getName())
                .set(role.getType() != null, ErpRole::getType, role.getType())
                .set(role.getPriceLimit() != null, ErpRole::getPriceLimit, role.getPriceLimit())
                .set(role.getDescription() != null, ErpRole::getDescription, role.getDescription())
                .update();
    }
    
    @Override
    public boolean updateRoleEnable(List<String> roleNames, boolean enabled, Long tenantId) {
        return lambdaUpdate()
                .in(ErpRole::getName, roleNames)
                .set(ErpRole::getEnabled, enabled)
                .eq(ErpRole::getTenantId, tenantId)
                .update();
    }
    
    @Override
    public Result<String> removeBatchByNames(List<String> roleNames, Long tenantId) {
        boolean remove = lambdaUpdate().in(ErpRole::getName, roleNames)
                .eq(ErpRole::getTenantId, tenantId)
                .remove();
        return remove ? Result.success("删除成功！") : Result.error("删除失败");
    }
    
    @Override
    public ErpRole getRoleByUserId(Long userId) {
        return baseMapper.getRoleByUserId(userId);
    }
    
    @Override
    public DTO<HomeDataVO> getHomeData(ErpUser user) {
        HomeQuery homeQuery = HomeQuery.of(user.getTenantId());
        HomeDataVO vo = baseMapper.getHomeData(homeQuery);
        
        DTO.removeTrailingZeros(vo);
        
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        vo.setSaleList(baseMapper.getHomeHistogram(user.getTenantId(), "销售", list));
        vo.setRetailList(baseMapper.getHomeHistogram(user.getTenantId(), "零售", list));
        vo.setPurchaseList(baseMapper.getPurchaseHomeHistogram(user.getTenantId(), "采购", list));
        return DTO.of(vo, homeDataVO -> {
            HomeDataVO homeData = BeanUtil.copyProperties(homeDataVO, HomeDataVO.class);
            ErpRole role = baseMapper.getRoleByUserId(user.getId());
            // 屏蔽首页采购价
            if (StrUtil.contains(role.getPriceLimit(), "1")) {
                List<String> names = Collections.singletonList("Purchase");
                DTO.shieldPrice(homeData, names);
                homeData.getPurchaseList().forEach(item -> item.setMoney(new BigDecimal("0")));
            }
            // 屏蔽首页零售价
            if (StrUtil.contains(role.getPriceLimit(), "2")) {
                List<String> names = Collections.singletonList("Retail");
                DTO.shieldPrice(homeData, names);
                homeData.getRetailList().forEach(item -> item.setMoney(new BigDecimal("0")));
            }
            // 屏蔽首页销售价
            if (StrUtil.contains(role.getPriceLimit(), "3")) {
                List<String> names = Collections.singletonList("Sale");
                DTO.shieldPrice(homeData, names);
                homeData.getSaleList().forEach(item -> item.setMoney(new BigDecimal("0")));
            }
            return homeData;
        });
    }
}
